home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-09-10 | 34.2 KB | 1,183 lines | [TEXT/MPS ] |
- (*+
- * File: UVUAssist.inc2.p - MacApp 3.0b2PQR compatible version
- *
- * Contains: VU assistance methods
- *
- * Written by: David Shayer
- *
- * Copyright: © 1991 by Apple Computer, Inc., all rights reserved.
- *
- * Version: 1.0d10
- *
- * Change History (most recent first):
-
- 9/10/91 JAS indicate 3.0b2PQR compatibility, change version
- 8/21/91 JAS adjust comments, change version
- 8/20/91 JAS fix syntax error
- 8/20/91 JAS remove debugging code
- 8/19/91 JAS Revise comments, change case of GridItemSupport to
- gridItemSupport
- 8/15/91 JAS Add GridItemSupport argument to IVUAssist
- 8/13/91 JAS Revise comments
- 8/13/91 JAS Change made in GetItemType so that kIncludeGridItems
- will determine whether TGridItems are ever identified for use
- 8/13/91 JAS Make changes in IVUAssist since VUAssist is now a descendant
- of TEvtHandler (sets idle frequency and installs cohandler).
- 8/13/91 JAS Changes in TGridItem implementation
- 8/13/91 JAS Use FirstSubViewThat in place of EachSubView wherever applicable
- 8/6/91 JAS Clean up change history
- 8/6/91 JAS Check for GridViewItems in GetItemType only if DlogViewItems is
- true, remove TVUAssist.DoFindWindowInfo (not needed)
- -*)
-
- {Historical Note: References to the "Mole" are equivalent to references to "Agent VU".
- "Agent VU" was previously called the "Mole".}
-
-
- { The mole sees MacApp windows as plain windows that are empty. MacApp
- doesn't put its controls in the control list, so V.U. won't even see standard
- Control Manager controls. The assistance proc updates the mole buffer before
- it is sent back to the V.U. host, telling it that there are items in the windows,
- and telling it about each item. We tell it that the windows are dialogs,
- because V.U. looks for a wider range of user interface items in dialogs.
-
- V.U. has its own hierarchy of user interface items, based largely on the types of
- interface items defined in Inside Mac which V.U. can obtain information about
- in non-MacApp applications. MacApp's user interface element hierarchy is the View hierarchy.
- Since the two hierarchies are not the same, VUAssist must perform a mapping between the
- two hierarchies. Many of these mappings are straight-forward, but a few require some
- explanation. The V.U. interface item hierarchy is as follows.
-
- |___ staticText
- |
- |___ editText
- |
- |___ picture
- contentItem-----|
- |___ icon
- |
- |___ userItem
- |
- |___ control-----|___ button
- |
- |___ checkBox
- |
- |___ radioButton
- |
- |___ scrollBar
- |
- |___ popup
-
- All V.U. interface items are considered contentItems. Some of these contentItems are
- typically found only in Dialog Manager dialogs in non-MacApp applications. These would
- be staticText, editText, picture, icon, and userItem. Controls are Control Manager controls
- which may appear in any window.
-
- The list of TView descendants which are mapped to V.U. interface items and the V.U. item
- to which they are mapped by V.U. by way of VUAssist is shown below.
-
- TStaticText ---------> staticText
- TEditText ---------> editText
- TPicture ---------> picture
- TIcon ---------> icon
- TButton ---------> button
- TCheckbox ---------> checkBox
- TRadio ---------> radioButton
- TScrollBar ---------> scrollBar
- TPopup ---------> popup
- TTextEdit ---------> editText
- (cells of TGridView -> contentItem) - an optional feature
-
- The last item, "cells of TGridView", deserves some explanation. TGridViews are a
- problem because unlike all the other items mentioned above, where there is exactly one
- MacApp object for each user interface item, there are many user interface items for a
- single TGridView object. V.U. does not yet directly support gridView types of objects.
- So there is special case code for TGridViews. Each cell in a grid is passed back as a
- "CUSTOM_ITEM". To V.U., a CUSTOM_ITEM is a user interface item which does not fall into
- any category more specific than contentItem. So from a V.U. script writer's perspective,
- cells in TGridView objects are V.U. contentItems.
-
- Note that the mapping of TGridView cells to contentItems is a feature which can be disabled.
- TVUAssist's IVUAssist method takes a boolean argument gridItemSupport. By passing 'false'
- to this method, the cells of TGridViews are invisible to V.U.. You may want to do this if
- your application has large gridviews or many gridviews. In this case treating each cell as
- an interface item may bog down V.U. in such a way that performance is not acceptable.
-
- You'll also note in the code that we include TPopup descriptions in response to V.U.'s requests
- for information about controls. This is because V.U. can normally only support popups which
- are implemented through the use of the popup CDEF found in System 7.0 or in the Mac Communications
- Toolbox. So V.U. expects them to be controls.}
-
-
-
- {========================================== TVUAssist ================================}
-
- {$S VUAssistSeg}
-
- {The MoleHook is declared as type C, which means it must be an external function.
- The actual code for MoleHook is in assembly. All it does is accept the call from the mole
- with a C interface, and then call TVUAssist.MoleAssist with a Pascal interface.}
- FUNCTION MoleHook (Select :integer; Input :Ptr; VAR OutputSize :integer;
- Result :integer) :OSErr; C; EXTERNAL;
-
-
- { IVUAssist initializes fMoleRefNum. fMoleRefNum contains the reference number of the
- mole driver, or 0 if no mole driver has been found yet. Also initializes VUAssist as an EvtHandler,
- sets idle frequency to kVUAssistIdleFreq, and installs cohandler. Also initializes fGridItemSupport
- according to input argument gridItemSupport.}
- PROCEDURE TVUAssist.IVUAssist(gridItemSupport: boolean);
- BEGIN
- INHERITED Initialize;
- INHERITED IEventHandler(NIL);
- fGridItemSupport:=gridItemSupport;
- fMoleRefNum:=0;
- SELF.OpenMoleDriver;
- SELF.SetIdleFreq(kVUAssistIdleFreq);
- gApplication.InstallCohandler(SELF, true);
- END;
-
-
- { Try to open the mole driver if there is one. }
- PROCEDURE TVUAssist.OpenMoleDriver;
- VAR
- PBRec :ParamBlockRec;
- Err :integer;
- MoleName :Str15;
- BEGIN
- MoleName:='.Mole';
- PBRec.ioCompletion:=NIL;
- PBRec.ioNamePtr:=@MoleName;
- PBRec.ioPermssn:=fsCurPerm;
- Err:=PBOpen (@PBRec, false);
- IF (PBRec.ioResult=noErr) THEN
- BEGIN
- fMoleRefNum:=PBRec.ioRefNum;
- SELF.ResumeMole;
- END;
- END;
-
-
- { Call this routine when the application is suspended by Multifinder, to let
- the mole know we are no longer the frontmost app. }
- PROCEDURE TVUAssist.SuspendMole;
- BEGIN
- SELF.SetDebuggerHook(NIL);
- END;
-
-
- { Call this routine when MultiFinder puts us back into the foreground. }
- PROCEDURE TVUAssist.ResumeMole;
- BEGIN
- SELF.SetDebuggerHook(@MoleHook);
- END;
-
-
-
- { Tell the mole the address of our assistance procedure.}
- PROCEDURE TVUAssist.SetDebuggerHook (NewHook :ProcPtr);
- CONST
- SET_ASSIST = 100;
- VAR
- PBRec :ParamBlockRec;
- Err :integer;
- LongPtr :^Longint;
- BEGIN
- IF (fMoleRefNum<>0) THEN
- BEGIN
- PBRec.ioCompletion:=NIL;
- PBRec.ioVRefNum:=0;
- PBRec.ioRefNum:=fMoleRefNum;
- PBRec.csCode:=SET_ASSIST;
- LongPtr:=@PBRec.csParam[0];
- LongPtr^:=LongInt(NewHook);
- Err:=PBControl (@PBRec, false);
- IF (PBRec.ioResult<>noErr) THEN
- WriteLn ('Error sending Mole control call');
- END;
- END;
-
-
-
- { This is the routine called by MoleHook. It dispatches out to the routines
- which actually assist the mole. }
- FUNCTION TVUAssist.MoleAssist (Select :integer; Input :Ptr; Output :Ptr;
- VAR OutputSize :integer; IntResult :integer) :integer;
- VAR
- Result :MoleError;
- ReturnValue :MoleError;
- BEGIN
- Result:=MoleError(IntResult);
- ReturnValue:=Result;
- CASE MoleSelectors(Select) OF
- SMenuInfo:
- BEGIN
- ReturnValue:=SELF.DoMenuInfo (Input, Output, OutputSize, Result);
- END;
- SMenuItems:
- BEGIN
- ReturnValue:=SELF.DoMenuItems (Input, Output, OutputSize, Result);
- END;
- SetMItemKey:
- BEGIN
- END;
- SFrontWind:
- BEGIN
- END;
- SFindWind:
- BEGIN
- END;
- SWindInfo:
- BEGIN
- ReturnValue:=SELF.DoSendWindowInfo (Input, Output, OutputSize, Result);
- END;
- SFindCtl:
- BEGIN
- ReturnValue:=SELF.DoFindControl (Input, Output, OutputSize, Result);
- END;
- SCtlInfo:
- BEGIN
- ReturnValue:=SELF.DoSendControlInfo (Input, Output, OutputSize, Result);
- END;
- SFindDItem:
- BEGIN
- END;
- SDItemInfo:
- BEGIN
- ReturnValue:=SELF.DoSendDlogItemInfo (Input, Output, OutputSize, Result);
- END;
- OTHERWISE
- BEGIN
- END;
- END; {case}
- MoleAssist:=integer(ReturnValue);
- END;
-
-
- {------------------------------------------------------------------------------------}
- { the routines for handling individual mole requests. Each routine handles
- exactly one mole request. }
-
- { Handle a request for specific menu items. The Mole can get info on menus in the
- menu bar, but we have to supply info on popup menus. }
- FUNCTION TVUAssist.DoMenuItems (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
- Result :MoleError) :MoleError;
- VAR
- MenuReqPtr :SendMenuItemsParamsPtr;
- MenuDescPtr :MoleDataBlockPtr;
- Popup :TPopup;
- BEGIN
- DoMenuItems:=Result; {initially, inherit result from mole}
- MenuReqPtr:=SendMenuItemsParamsPtr(Input);
- MenuDescPtr:=MoleDataBlockPtr(Output);
-
- { We don't need to respond when V.U. wants to find menus by rank (indicated by a menu_ID of 0).
- We do need to supply information about popups when the specified ID is non-zero. }
- IF MenuReqPtr^.menu_ID<>0 THEN
- BEGIN { find menu by menu ID }
- IF (Result<>mNoErr) THEN
- BEGIN
- Popup:=SELF.MenuIDToPopup (MenuReqPtr^.menu_ID);
- IF Popup<>NIL THEN
- BEGIN
- DoMenuItems:=SELF.FillPopupItemDesc (Popup, RANK_OF_THE_INVISIBLE,
- MenuReqPtr^.start_item, MenuReqPtr^.stop_item, MenuDescPtr, OutputSize);
- END;
- END;
- END;
- END;
-
-
- { Handle a request for menu info. The Mole can get info on menus in the
- menu bar, but we have to supply info on popup menus. }
- FUNCTION TVUAssist.DoMenuInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
- Result :MoleError) :MoleError;
- VAR
- MenuReqPtr :SendMenuInfoParamsPtr;
- MenuDescPtr :MoleMenuInfoPtr;
- Popup :TPopup;
- BEGIN
- DoMenuInfo:=Result; {initially, inherit result from mole}
- MenuReqPtr:=SendMenuInfoParamsPtr(Input);
- MenuDescPtr:=MoleMenuInfoPtr(Output);
-
- { We don't need to respond when V.U. wants to find menus by rank (indicated by a menu_ID of 0).
- We do need to supply information about popups when the specified ID is non-zero. }
- IF MenuReqPtr^.menu_ID<>0 THEN
- BEGIN { find menu by menu ID }
- IF (Result<>mNoErr) THEN
- BEGIN
- Popup:=SELF.MenuIDToPopup (MenuReqPtr^.menu_ID);
- IF Popup<>NIL THEN
- BEGIN
- SELF.FillPopupDesc (Popup, RANK_OF_THE_INVISIBLE, MenuDescPtr, OutputSize);
- DoMenuInfo:=mNoErr;
- END;
- END;
- END;
- END;
-
-
-
- { Revise the values of the controlCount and numItems fields of the MoleWDescPtr, given
- knowledge of MacApp views. Also update validFlags and windowKind fields. WindowKind is set
- to dialogKind so that V.U. will look for things that it can normally only see in dialogs
- (such as icons and pictures) }
- FUNCTION TVUAssist.DoSendWindowInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
- Result :MoleError) :MoleError;
- VAR
- WindReqPtr :DWindReqPtr;
- WindDescPtr :MoleWDescPtr;
- Window :TWindow;
- BEGIN
- DoSendWindowInfo:=Result; {initially, inherit result from mole}
- WindReqPtr:=DWindReqPtr(Input);
- WindDescPtr:=MoleWDescPtr(Output);
- Window:=SELF.RankToWindow (WindReqPtr^);
- IF Window<>NIL THEN
- BEGIN
- WindDescPtr^.validFlags := BOR (WindDescPtr^.validFlags, VCTLCNT_MASK);
- WindDescPtr^.validFlags := BOR (WindDescPtr^.validFlags, VITEMCNT_MASK);
- WindDescPtr^.windowKind:=dialogKind;
- WindDescPtr^.controlCount:=SELF.ViewCount (Window, false);
- WindDescPtr^.numItems:=SELF.ViewCount (Window, true);
- { OutputSize is filled in by the mole }
- DoSendWindowInfo:=mNoErr;
- END;
- END;
-
-
- { The mole sends us a point location in global coordinates. We need to figure out
- which window and which control that point is in (if any), and send back info about
- that control. V.U. utilizes this routine for Control Manager controls (TCtlMgr) only.}
- FUNCTION TVUAssist.DoFindControl (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
- Result :MoleError) :MoleError;
- VAR
- CtrlReqPtr :SendFindControlParamPtr;
- CtrlDescPtr :MoleCDescPtr;
- TargetPoint :SendFindControlParam;
- part :integer;
- wind :WindowPeek;
- SavePort :GrafPtr;
- Control :TCtlMgr;
- Rank :integer;
- SaveCtlList :ControlHandle;
- WhichCtl :ControlHandle;
- Window :TWindow;
- VPt :VPoint;
- BEGIN
- DoFindControl:=Result; {initially, inherit result from mole}
- CtrlReqPtr:=SendFindControlParamPtr(Input);
- TargetPoint:=CtrlReqPtr^;
- CtrlDescPtr:=MoleCDescPtr(Output);
-
- part:=FindWindow (TargetPoint, WindowPtr(wind));
- { The mole also tests for part=inSysWindow, but we'll let the mole handle those cases}
- IF (wind<>NIL) AND (part=inContent) THEN
- BEGIN
- Window:=gApplication.WMgrToWindow(WindowPtr(wind));
- IF (Window<>NIL) THEN
- BEGIN
- Control:=SELF.PointToControl (Window, TargetPoint, Rank);
- IF Control<>NIL THEN
- BEGIN
- part:=-1;
- { Get the control part code. Controls are not kept in the controllist,
- so we temporarily put them in there. Also, they are in their subviews
- local coordinate system, so we must convert targetpoint. }
- GetPort (SavePort);
- SetPort (WindowPtr(wind));
- IF Window.Focus THEN
- BEGIN
- SaveCtlList:=wind^.controlList;
- wind^.controlList:=Control.fCMgrControl;
- SELF.GlobalToWindow (Window, TargetPoint, VPt);
- SELF.WindowToView (Control, VPt, TargetPoint);
- part:=FindControl (TargetPoint, WindowPtr(wind), WhichCtl);
- wind^.controlList:=SaveCtlList;
- END;
- SetPort (SavePort);
-
- IF (SELF.FillCtrlDesc (CtrlDescPtr, part, SELF.WindowToRank(wind),
- Rank, Control, OutputSize)) THEN
- BEGIN
- DoFindControl:=mNoErr;
- END;
- END;
- END;
- END;
- END;
-
-
- { Read the input parameter to see which control V.U. wants info on, then
- fill in the SendCtlInfoParamsPtr record. The mole can't gather any info about
- MacApp controls without our help, so we fill in the whole record, except for part,
- which doesn't apply.}
- FUNCTION TVUAssist.DoSendControlInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
- Result :MoleError) :MoleError;
- VAR
- CtrlReqPtr :SendCtlInfoParamsPtr;
- CtrlDescPtr :MoleCDescPtr;
- Window :TWindow;
- Control :TControl;
- gridItem :TGridItem;
- BEGIN
- DoSendControlInfo:=Result; {initially, inherit result from mole}
- gridItem:=NIL;
- CtrlReqPtr:=SendCtlInfoParamsPtr(Input);
- CtrlDescPtr:=MoleCDescPtr(Output);
-
- Window:=SELF.RankToWindow (CtrlReqPtr^.window_rank);
- IF Window<>NIL THEN
- BEGIN
- Control:=TControl(SELF.RankToItem (Window, CtrlReqPtr^.control_rank, false, gridItem));
- IF Control<>NIL THEN
- BEGIN
- IF (SELF.FillCtrlDesc (CtrlDescPtr, -1, CtrlReqPtr^.window_rank,
- CtrlReqPtr^.control_rank, Control, OutputSize)) THEN
- BEGIN
- DoSendControlInfo:=mNoErr;
- END;
- END;
- END;
- END;
-
-
- { Read the input to see which dialog item in which window V.U. wants data on, and
- fill in the dialogiteminfo record. }
- FUNCTION TVUAssist.DoSendDlogItemInfo (Input :Ptr; Output :Ptr; VAR OutputSize :integer;
- Result :MoleError) :MoleError;
- VAR
- DlogReqPtr :SendDItemInfoPtr;
- DlogDescPtr :MoleDItemInfoPtr;
- Window :TWindow;
- View :TView;
- gridItem :TGridItem;
- BEGIN
- DoSendDlogItemInfo:=Result; {initially, inherit result from mole}
- gridItem:=NIL;
- DlogReqPtr:=SendDItemInfoPtr(Input);
- DlogDescPtr:=MoleDItemInfoPtr(Output);
-
- Window:=SELF.RankToWindow (DlogReqPtr^.window_rank);
- IF Window<>NIL THEN
- BEGIN
- View:=SELF.RankToItem (Window, DlogReqPtr^.item_num, true, gridItem);
- IF View<>NIL THEN
- BEGIN
- SELF.FillDlogItemDesc (DlogDescPtr, Window, DlogReqPtr^.window_rank,
- DlogReqPtr^.item_num, View, OutputSize, gridItem);
- DoSendDlogItemInfo:=mNoErr;
- END;
- END;
- END;
-
-
- {------------------------------------------------------------------------------------}
- { routines for filling in mole data structures }
-
- { Given a TPopup object, fill in the mole's menu descriptor record. }
- PROCEDURE TVUAssist.FillPopupDesc (Popup: TPopup; MenuRank: integer;
- MenuDescPtr :MoleMenuInfoPtr; VAR OutputSize :integer);
- VAR
- TheMenuHdl :MenuHandle;
- BEGIN
- TheMenuHdl := Popup.GetMenuHandle;
- WITH MenuDescPtr^ DO
- BEGIN
- num_items:=CountMItems (TheMenuHdl);
- rank:=MenuRank;
- left_edge:=0;
- menuID:=Popup.GetMenuID;
- menuWidth:=TheMenuHdl^^.menuWidth;
- menuHeight:=TheMenuHdl^^.menuHeight;
- enableFlags:=TheMenuHdl^^.enableFlags;
- text_name:=TheMenuHdl^^.menuData;
-
- { this ugly thing computes the length (bytes used) of MoleMenuInfo }
- OutputSize:=sizeof(MoleMenuInfo) - (255-length(text_name));
- END;
- END;
-
-
- { Given a TPopup object, fill in the mole's menuitem descriptor record. }
- FUNCTION TVUAssist.FillPopupItemDesc (Popup: TPopup; MenuRank: integer; start: integer;
- stop: integer; MenuItemDescPtr :MoleDataBlockPtr; VAR OutputSize :integer) :MoleError;
-
- { this function depends upon Ptr being a pointer to a single byte }
- FUNCTION SeekMenuItem (ItemNum: integer; MenuHdl: MenuHandle) :Ptr;
- VAR
- SeekPtr :Ptr;
- SeekNum :integer;
- BEGIN
- SeekNum:=1;
- SeekPtr:= Ptr(ORD4(@MenuHdl^^.menuData) + length(MenuHdl^^.menuData) + 1);
- WHILE (SeekNum<ItemNum) AND (SeekPtr^<>0) DO
- BEGIN
- SeekPtr:= Ptr(ORD4(SeekPtr) + SeekPtr^ + ADDITIONAL_MENU_ITEM_DATA);
- SeekNum:=SeekNum+1;
- END;
- SeekMenuItem:=SeekPtr;
- END;
-
- VAR
- StartPtr :Ptr;
- StopPtr :Ptr;VAR
- TheMenuHdl :MenuHandle;
- BEGIN
-
- TheMenuHdl := Popup.GetMenuHandle;
-
- FillPopupItemDesc:=mNoErr;
- IF (start>CountMItems (TheMenuHdl)) OR (start<1) THEN
- BEGIN
- FillPopupItemDesc:=mBadMenuItemIndex;
- EXIT (FillPopupItemDesc);
- END;
-
- IF stop>CountMItems (TheMenuHdl) THEN
- BEGIN
- stop:=CountMItems (TheMenuHdl);
- FillPopupItemDesc:=mBadLastMenuItemIndex;
- END;
-
- StartPtr:=SeekMenuItem (start, TheMenuHdl);
- StopPtr:=SeekMenuItem (stop+1, TheMenuHdl);
- IF (StartPtr=NIL) OR (StopPtr=NIL) THEN
- BEGIN
- FillPopupItemDesc:=mBadMenuItemIndex;
- EXIT (FillPopupItemDesc);
- END;
- MenuItemDescPtr^.blockLength:=stop-start+1;
- BlockMove (StartPtr, @MenuItemDescPtr^.dataBlock[0], ORD4(StopPtr)-ORD4(StartPtr));
-
- { this ugly thing computes the length (bytes used) of MoleDataBlock }
- OutputSize:=sizeof(integer) + (ORD4(StopPtr)-ORD4(StartPtr));
- END;
-
-
- { Fill in a mole control descriptor record. Valid descendants of TControl are descendants of
- TCtlMgr and TPopup. Will return false if TControl is not a descendant of TCtlMgr or TPopup.}
- FUNCTION TVUAssist.FillCtrlDesc (CtrlDescPtr :MoleCDescPtr; thePart :integer;
- WindRank :integer; ControlRank :integer; Control :TControl; VAR OutputSize :integer): BOOLEAN;
- VAR
- dummy :longint;
- ControlHdl :ControlHandle;
- aVRect :VRect;
- TheMenuHdl :MenuHandle;
- BEGIN
- FillCtrlDesc:=FALSE;
- IF Member (Control, TPopup) THEN
- BEGIN
- TheMenuHdl := TPopup(Control).GetMenuHandle;
- WITH CtrlDescPtr^ DO
- BEGIN
- validFlags:=VALL_C_MASK;
- IF thePart=-1 THEN
- BEGIN
- dummy:=validFlags;
- BClr (dummy, VCPART);
- validFlags:=dummy;
- END;
- owner_rank:=WindRank;
- Control.GetExtent (aVRect);
- VRectToRect(aVRect, ctlRect);
- SELF.ViewRectToWindowRect (ctlRect, Control);
-
- ctlValue:=TPopup(Control).GetCurrentItem;
- ctlMin:=1;
- ctlMax:=CountMItems(TheMenuHdl);
- ctlHilite:=0;
- IF thePart=-1 THEN
- part:=0
- ELSE
- part:=thePart;
- ctlRank:=ControlRank;
- ctlDefID:=POPUP_CDEF*16;
- popupMenuID:=TPopup(Control).GetMenuID;
- text_name:=TheMenuHdl^^.menuData;
-
- { this ugly thing computes the length (bytes used) of CtrlDescPtr }
- OutputSize:=sizeof(MoleControlDescriptor) - (255-length(text_name));
- END;
- END
- ELSE IF Member (Control, TCtlMgr) THEN {non-popup member of TCtlMgr}
- BEGIN
- ControlHdl:=TCtlMgr(Control).fCMgrControl;
- WITH CtrlDescPtr^, ControlHdl^^ DO
- BEGIN
- validFlags:=VALL_C_MASK;
- IF thePart=-1 THEN
- BEGIN
- dummy:=validFlags;
- BClr (dummy, VCPART);
- validFlags:=dummy;
- END;
- owner_rank:=WindRank;
- ctlRect:=contrlRect;
- SELF.ViewRectToWindowRect (ctlRect, Control);
- ctlValue:=contrlValue;
- ctlMin:=contrlMin;
- ctlMax:=contrlMax;
- ctlHilite:=contrlHilite;
- IF thePart=-1 THEN
- part:=0
- ELSE
- part:=thePart;
- ctlRank:=ControlRank;
- ctlDefID:=BAND(BSR(longint(contrlDefProc), 24), $7);
- IF Member (Control, TScrollBar) THEN
- ctlDefID:=ctlDefID+16;
- popupMenuID:=0;
- text_name:=contrlTitle;
-
- { this ugly thing computes the length (bytes used) of CtrlDescPtr }
- OutputSize:=sizeof(MoleControlDescriptor) - (255-length(text_name));
- FillCtrlDesc:=TRUE;
- END;
- END;
- END;
-
-
- PROCEDURE TVUAssist.ViewRectToWindowRect (VAR aRect :Rect; aView :TView);
- VAR
- VPt :VPoint;
- BEGIN
- PtToVPt(aRect.topLeft, VPt);
- aView.LocalToWindow (VPt);
- aRect.topLeft:=VPtToPt (VPt);
- PtToVPt(aRect.botRight, VPt);
- aView.LocalToWindow (VPt);
- aRect.botRight:=VPtToPt (VPt);
- END;
-
-
- { Fill in a mole dialog item descriptor record }
- PROCEDURE TVUAssist.FillDlogItemDesc (DlogDescPtr :MoleDItemInfoPtr; Window :TWindow;
- WindRank :integer; ItemRank :integer; Item :TView; VAR OutputSize :integer; gridItem :TGridItem);
- VAR
- aVRect :VRect;
- TextLen :longint;
- TextHdl :Handle;
- ItemKind :ViewItems;
- aCell :GridCell;
- VBox :VRect;
- BEGIN
- WITH DlogDescPtr^ DO
- BEGIN
- ItemKind:=SELF.GetItemType (Item, true, true);
- { fill in box, itemType, item_enabled, has_text and text_name here }
- CASE ItemKind OF
- VINotMember:
- ;
- VIButton:
- BEGIN
- TCtlMgr(Item).ControlArea (VBox);
- VRectToRect(VBox, box);
- itemType:=btnCtrlItem;
- item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
- has_text:=TRUE;
- TCtlMgr(Item).GetText (text_name);
- END;
- VIRadio:
- BEGIN
- TCtlMgr(Item).ControlArea (VBox);
- VRectToRect(VBox, box);
- itemType:=radCtrlItem;
- item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
- has_text:=TRUE;
- TCtlMgr(Item).GetText (text_name);
- END;
- VICheckBox:
- BEGIN
- TCtlMgr(Item).ControlArea (VBox);
- VRectToRect(VBox, box);
- itemType:=chkCtrlItem;
- item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
- has_text:=TRUE;
- TCtlMgr(Item).GetText (text_name);
- END;
- VIScrollBar:
- BEGIN
- TCtlMgr(Item).ControlArea (VBox);
- VRectToRect(VBox, box);
- itemType:=resCtrlItem;
- item_enabled:=TCtlMgr(Item).IsCMgrVisible AND Item.IsActive;
- has_text:=TRUE;
- TCtlMgr(Item).GetText (text_name);
- END;
- VIStatText:
- BEGIN
- Item.GetExtent (aVRect);
- VRectToRect(aVRect, box);
- itemType:=statText;
- item_enabled:=FALSE;
- has_text:=TRUE;
- TStaticText(Item).GetText (text_name);
- END;
- VIEditText:
- BEGIN
- Item.GetExtent (aVRect);
- VRectToRect(aVRect, box);
- itemType:=editText;
- item_enabled:=Item.IsActive;
- has_text:=TRUE;
- TStaticText(Item).GetText (text_name);
- END;
- VIIcon:
- BEGIN
- Item.GetExtent (aVRect);
- VRectToRect(aVRect, box);
- itemType:=iconItem;
- item_enabled:=Item.IsActive;
- has_text:=FALSE;
- item_text_ptr:=NIL;
- END;
- VIPopup:
- BEGIN
- Item.GetExtent (aVRect);
- VRectToRect(aVRect, box);
- itemType:=resCtrlItem;
- item_enabled:=Item.IsActive;
- has_text:=FALSE;
- item_text_ptr:=NIL;
- END;
- VIPicture:
- BEGIN
- Item.GetExtent (aVRect);
- VRectToRect(aVRect, box);
- itemType:=picItem;
- item_enabled:=Item.IsActive;
- has_text:=FALSE;
- item_text_ptr:=NIL;
- END;
- VITextEdit:
- BEGIN
- Item.GetExtent (aVRect);
- VRectToRect(aVRect, box);
- itemType:=editText;
- item_enabled:=Item.IsActive;
- has_text:=TRUE;
- TextHdl:=TTEView(Item).ExtractText;
- TextLen:=GetHandleSize (TextHdl);
- IF TextLen>255 THEN TextLen:=255;
- BlockMove (TextHdl^, @text_name, TextLen);
- END;
- VIGridItem:
- BEGIN
- gridItem.GetExtent (aVRect);
- VRectToRect(aVRect, box);
- itemType:=CUSTOM_ITEM;
- item_enabled:=gridItem.fGridView.IsActive;
- IF Member (Item, TTextGridView) THEN
- BEGIN {item has text associated with it}
- has_text:=TRUE;
- aCell.v:=gridItem.fRow;
- aCell.h:=gridItem.fColumn;
- TTextGridView(gridItem.fGridView).GetText (aCell, text_name);
- END
- ELSE {item may not have text associated with it}
- BEGIN
- has_text:=FALSE;
- item_text_ptr:=NIL;
- END;
- END;
- END; { case }
- SELF.ViewRectToWindowRect (box, Item);
- { fill in ctlRank, owner_rank, and item_num here }
- ctlRank:=SELF.ItemToRank (Window, Item, false);
- owner_rank:=WindRank;
- item_num:=ItemRank;
-
- { this ugly thing computes the length (bytes used) of MoleDItemInfo }
- IF ItemKind<>VINotMember THEN
- OutputSize:=sizeof(MoleDItemInfo) - (255-length(text_name));
-
- IF gridItem <> NIL THEN
- gridItem.Free;
- END; { with }
- END;
-
-
- {------------------------------------------------------------------------------------}
- { routines for searching through the view tree to find particular views }
-
- { Given the rank (z-order) of a window, return the window object. Invisible
- windows are not considered to be in the window list, for ranking purposes. }
- FUNCTION TVUAssist.RankToWindow (Rank :integer) :TWindow;
- VAR
- i: integer;
- Window :WindowPeek;
- BEGIN
- RankToWindow:=NIL;
- i:=1;
- Window:=WindowPeek(FrontWindow);
- WHILE Window<>NIL DO
- BEGIN
- IF Window^.visible THEN
- BEGIN
- IF i=Rank THEN
- BEGIN
- RankToWindow:=gApplication.WMgrToWindow(WindowPtr(Window));
- LEAVE;
- END;
- i:=i+1;
- END;
- Window:=Window^.nextWindow;
- END;
- END;
-
-
- {Given a window ptr, return the window's rank (z-order).}
- FUNCTION TVUAssist.WindowToRank (WindToFind :WindowPeek) :integer;
- VAR
- i: integer;
- Window :WindowPeek;
- BEGIN
- WindowToRank:=0;
- i:=1;
- Window:=WindowPeek(FrontWindow);
- WHILE Window<>NIL DO
- BEGIN
- IF Window^.visible THEN
- BEGIN
- IF WindToFind=Window THEN
- BEGIN
- WindowToRank:=i;
- LEAVE;
- END;
- i:=i+1;
- END;
- Window:=Window^.nextWindow;
- END;
- END;
-
-
- { Convert a point in global coordinates to window coordinates. }
- PROCEDURE TVUAssist.GlobalToWindow (Window :TWindow; Pt :Point; VAR VPt :VPoint);
- VAR
- SavePort :GrafPtr;
- TargetPoint :Point;
- BEGIN
- VPt.h:=0;
- VPt.v:=0;
- GetPort (SavePort);
- SetPort (Window.GetGrafPort);
- IF Window.Focus THEN
- BEGIN
- TargetPoint:=Pt;
- GlobalToLocal (TargetPoint);
- Window.QDToViewPt(TargetPoint, VPt);
- END;
- SetPort (SavePort);
- END;
-
-
- { Convert a point in window coordinates to a subview's coordinates. Return both a
- VPoint and a QDPoint. }
- PROCEDURE TVUAssist.WindowToView (View :TView; VAR VPt :VPoint; VAR Pt :Point);
- BEGIN
- Pt.h:=0;
- Pt.v:=0;
- View.WindowToLocal(VPt);
- IF View.Focus THEN
- Pt:=View.ViewToQDPt (VPt);
- END;
-
-
-
- { In the front (active) window, given the menu ID of a popup item, return the
- popup menu object and its rank. }
- FUNCTION TVUAssist.MenuIDToPopup (MenuID :integer) :TPopup;
- VAR
- foundView :TView;
- dummyView :TView;
- window :TWindow;
-
- FUNCTION TestSubID(theSubView: TView): BOOLEAN;
- BEGIN
- IF theSubView.IsShown THEN
- BEGIN
- IF SELF.GetItemType (theSubView, false, false)=VIPopup THEN
- BEGIN
- IF TPopup(theSubView).fMenuID=MenuID THEN
- foundView:=theSubView;
- END;
- IF (foundView=NIL) THEN
- dummyView:=theSubView.FirstSubViewThat (TestSubID);
- END;
- TestSubID:=foundView <> NIL;
- END;
-
- BEGIN
- foundView:=NIL;
- window:=gApplication.GetActiveWindow;
- IF (Window<>NIL) & (Window.IsShown) THEN
- dummyView:=Window.FirstSubViewThat (TestSubID);
- MenuIDToPopup:=TPopup(foundView);
- END;
-
-
- { Given a window object and a point in global coordinates,
- find the control which is under that point. Only descendants of
- TCtlMgr are considered.}
- FUNCTION TVUAssist.PointToControl (Window :TWindow; Pt :Point; VAR Rank :integer) :TCtlMgr;
- VAR
- foundView : TView;
- dummyView : TView;
- VPt : VPoint;
- TestPoint : VPoint;
- DummyPoint : Point;
- aRect : Rect;
-
- FUNCTION TestSubView(theSubView: TView): BOOLEAN;
- VAR
- ItemType :ViewItems;
- BEGIN
- IF theSubView.IsShown THEN
- BEGIN
- IF Member (theSubView, TCtlMgr) THEN
- BEGIN
- TestPoint:=VPt;
- SELF.WindowToView (theSubView, TestPoint, DummyPoint);
- IF theSubView.ContainsMouse(TestPoint) THEN
- foundView:=theSubView;
- END;
- IF (foundView=NIL) THEN
- dummyView:=theSubView.FirstSubViewThat (TestSubView);
- END;
- TestSubView:=foundView <> NIL;
- END;
-
- BEGIN
- foundView:=NIL;
- SELF.GlobalToWindow (Window, Pt, VPt);
- IF Window.IsShown THEN
- dummyView:=Window.FirstSubViewThat (TestSubView);
- Rank:=SELF.ItemToRank (Window, foundView, false);
- PointToControl:=TCtlMgr(foundView);
- END;
-
-
- { Walk the view hierarchy tree, counting the number of user interface items.
- Only visible views and items are counted. }
- FUNCTION TVUAssist.ViewCount (Window :TWindow; DlogViewItems :Boolean) :integer;
- VAR
- ItemCount :integer;
-
- PROCEDURE DoToSubView(theSubView: TView);
- VAR
- ItemType: ViewItems;
- BEGIN
- IF theSubView.IsShown THEN
- BEGIN
- ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
- IF ItemType<>VINotMember THEN
- BEGIN
- IF ItemType=VIGridItem THEN
- ItemCount:=ItemCount+SELF.CountGridItems (TGridView(theSubView))
- ELSE
- ItemCount := ItemCount + 1;
- END;
- IF Member (theSubView, TView) THEN
- theSubView.EachSubView (DoToSubView);
- END;
- END;
-
- BEGIN
- ItemCount:=0;
- IF Window.IsShown THEN
- Window.EachSubView (DoToSubView);
- ViewCount:=ItemCount;
- END;
-
-
- {Given a control or dialog item (View), and the window its in (Window), return its rank. }
- FUNCTION TVUAssist.ItemToRank (Window :TWindow; View :TView; DlogViewItems :Boolean) :integer;
- VAR
- ItemCount :integer;
- Rank :integer;
- dummyView :TView;
-
- FUNCTION TestSubView(theSubView: TView): BOOLEAN;
- VAR
- ItemType: ViewItems;
- BEGIN
- IF theSubView.IsShown THEN
- BEGIN
- ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
- IF ItemType<>VINotMember THEN
- BEGIN
- IF ItemType=VIGridItem THEN
- BEGIN
- IF (Member(View, TGridItem)) & (theSubView=TGridItem(View).fGridView) THEN
- Rank:=ItemCount+TGridItem(View).fRank
- ELSE
- ItemCount:=ItemCount+SELF.CountGridItems (TGridView(theSubView));
- END
- ELSE BEGIN
- ItemCount := ItemCount + 1;
- IF theSubView=View THEN
- Rank:=ItemCount;
- END;
- END;
- IF (Rank=0) THEN
- dummyView:=theSubView.FirstSubViewThat (TestSubView);
- END;
- TestSubView:=Rank <> 0;
- END;
-
- BEGIN
- Rank:=0;
- ItemCount:=0;
- IF Window.IsShown THEN
- dummyView:=Window.FirstSubViewThat (TestSubView);
- ItemToRank:=Rank;
- END;
-
-
- { Given a window object and the rank (z-order) of an item, return the item object. If
- the item is a cell of a TGridView object, return that object in gridItem.}
- FUNCTION TVUAssist.RankToItem (Window :TWindow; Rank :integer; DlogViewItems :Boolean;
- VAR gridItem: TGridItem) :TView;
- VAR
- ItemCount :integer;
- foundView :TView;
- dummyView :TView;
-
- FUNCTION TestSubView(theSubView: TView): BOOLEAN;
- VAR
- ItemType: ViewItems;
- GridCount: integer;
- BEGIN
- IF theSubView.IsShown THEN
- BEGIN
- ItemType:=SELF.GetItemType (theSubView, DlogViewItems, DlogViewItems);
- IF ItemType<>VINotMember THEN
- BEGIN
- IF (ItemType=VIGridItem) THEN
- BEGIN
- GridCount:=SELF.CountGridItems (TGridView(theSubView));
- IF (Rank>ItemCount) AND (Rank<=ItemCount+GridCount) THEN
- BEGIN
- New (gridItem);
- FailNil (gridItem);
- gridItem.IGridItem (TGridView(theSubView), Rank-ItemCount);
- foundView:=theSubView;
- END;
- ItemCount := ItemCount + GridCount;
- END
- ELSE BEGIN
- ItemCount := ItemCount + 1;
- IF ItemCount=Rank THEN
- foundView:=theSubView;
- END;
- END;
- IF (foundView=NIL) THEN
- dummyView:=theSubView.FirstSubViewThat (TestSubView);
- END;
- TestSubView:=foundView <> NIL;
- END;
-
- BEGIN
- foundView:=NIL;
- ItemCount:=0;
- IF Window.IsShown THEN
- dummyView:=Window.FirstSubViewThat (TestSubView);
- RankToItem:=foundView;
- END;
-
-
- { Report the number of items in a TGridView. This is here so it can
- be easily overridden if you only want rows or columns to show up as
- seperate user interface items, instead of each cell. }
- FUNCTION TVUAssist.CountGridItems (theGridView: TGridView): integer;
- BEGIN
- CountGridItems:=theGridView.fNumOfRows*theGridView.fNumOfCols;
- END;
-
-
-
- {Given a view item and the control/dialog item flag, decide if this
- view object is a control if the flag=ControlsOnly, or if its a dialog
- item if the flag=DialogItems, or if its neither. Of course, MacApp
- doesn't have a concept of dialog items, so we improvise. Here are the criteria.
- Any descendent of TCtlMgr is a control. Descendants of TPopup are also classified
- as contols because V.U. can normally only deal with popups which utilize the popup
- CDEF. So V.U. expects popups to be controls.
-
- Descendents of TTEView and some descendants of TControl (specifically TEditText,
- TStaticText, TIcon, TPicture, and TGridView) are considered to be DialogItems for V.U.'s sake.
- GridViewItems are considered along with other DlogViewItems only if GridViewItems parameter
- is true.}
- FUNCTION TVUAssist.GetItemType (Item :TView; DlogViewItems :Boolean;
- GridViewItems: Boolean) :ViewItems;
- BEGIN
- GetItemType:=VINotMember;
- IF Member (Item, TPopup) THEN
- GetItemType:=VIPopup
- ELSE IF Member (Item, TRadio) THEN
- GetItemType:=VIRadio
- ELSE IF Member (Item, TCheckBox) THEN
- GetItemType:=VICheckBox
- ELSE IF Member (Item, TScrollBar) THEN
- GetItemType:=VIScrollBar
- ELSE IF Member (Item, TButton) THEN
- GetItemType:=VIButton;
- IF DlogViewItems THEN
- BEGIN
- IF Member (Item, TEditText) THEN {TEditText descends from TStaticText}
- GetItemType:=VIEditText
- ELSE IF Member (Item, TStaticText) THEN
- GetItemType:=VIStatText
- ELSE IF Member (Item, TIcon) THEN
- GetItemType:=VIIcon
- ELSE IF Member (Item, TPicture) THEN
- GetItemType:=VIPicture
- ELSE IF Member (Item, TTEView) AND NOT Member (Item, TDialogTEView) THEN
- GetItemType:=VITextEdit;
- IF (fGridItemSupport AND GridViewItems) THEN
- BEGIN
- IF Member (Item, TGridView) THEN
- BEGIN
- GetItemType:=VIGridItem;
- END;
- END;
- END;
-
- END;
-
-
-
- {========================================== TGridItem ================================}
-
- {$S VUAssistSeg}
-
- { Instantiate a TGridItem object, and fill in its fields.. This is here
- so it can be overridden if you only want rows or columns to show
- up as seperate user interface items, instead of each individual cells. }
- PROCEDURE TGridItem.IGridItem (theGridView: TGridView; Rank: integer);
- BEGIN
- SELF.fGridView:=theGridView;
- SELF.fRank:=Rank;
- SELF.fRow:=(Rank-1) DIV theGridView.fNumOfCols +1;
- SELF.fColumn:=(Rank-1) MOD theGridView.fNumOfCols +1;
- END;
-
- { Provide the bounding rect of a griditem }
- PROCEDURE TGridItem.GetExtent (VAR itsExtent: VRect);
- VAR
- aCell: GridCell;
- BEGIN
- aCell.v:=fRow;
- aCell.h:=fColumn;
- fGridView.CellToVRect (aCell, itsExtent);
- END;
-
-
- { call the LocalToWindow method of the GridView associated with the griditem }
- PROCEDURE TGridItem.LocalToWindow(VAR thePoint: VPoint);
- BEGIN
- fGridView.LocalToWindow(thePoint);
- END;
-
-